#pragma once

#include "Common.hpp"
#include "ThreadCache.hpp"
#include "ObjectPool.hpp"

// 对外提供的函数，进行内存申请
static void *ConcurrentAlloc(size_t size)
{
    // 无法直接从 ThreadCache 申请
    // 如果 128*8*1024 >= size > 32*8*1024 ——> 直接从PageCache申请
    // 如果 size > 128*8*1024 ——> 直接从堆上申请
    if (size > MAX_BYTES)
    {
        size_t alignNum = SizeClass::RoundUp(size); // 计算对齐数
        size_t kpage = alignNum >> PAGE_SHIFT;
        PageCache::GetInstance()->Get_PageMutex().lock();
        Span *span = PageCache::GetInstance()->NewSpan(kpage);
        span->objSize_ = size;
        PageCache::GetInstance()->Get_PageMutex().unlock();

        void *ptr = (void *)(span->pageId_ << PAGE_SHIFT);
        return ptr;
    }
    else
    {
        if (pTLSThreadCache == nullptr)
        {
            // pTLSThreadCache = new ThreadCache
            static Memorypool<ThreadCache> TcPool;
            pTLSThreadCache = TcPool.New();
        }

        return pTLSThreadCache->Allocate(size);
    }
}

// 对外提供的函数，进行内存释放
static void ConcurrentFree(void *obj)
{
    Span *span = PageCache::GetInstance()->MapObjectToSpan(obj); // 属于哪个Span
    size_t size = span->objSize_;

    if (size > MAX_BYTES)
    {
        PageCache::GetInstance()->Get_PageMutex().lock();
        PageCache::GetInstance()->ReleaseSpanToPageCache(span);
        PageCache::GetInstance()->Get_PageMutex().unlock();
    }
    else
    {
        assert(obj);
        assert(pTLSThreadCache);

        pTLSThreadCache->Deallocate(obj, size);
    }
}